import { Injectable, Logger } from "@nestjs/common";
import { Interval, SchedulerRegistry } from "@nestjs/schedule";
import { DeviceService } from "src/device/device.service";
import { WsEvent } from "../ws.event.enum";
import { Server } from "socket.io";
import { OnlineUserItem } from "src/common/model";
import { MySocket } from "../socket.gateway";
import { RolesGuard } from "src/FGIP/guard/role.guard";
import { Perm as AdminPerm } from "src/user/controller/admin.controller";
import { ROOT_USER_ID } from "src/constant";

@Injectable()
export class BroadcastService {
    private readonly logger = new Logger(BroadcastService.name);

    private nextBroadcastType: "cpu_usage" | "memory" = "cpu_usage";

    private historyData: Record<string, string> = {};

    server?: Server;

    constructor(
        private readonly deviceService: DeviceService,
        private readonly schedulerRegistry: SchedulerRegistry,
    ) {}

    @Interval("broadcastRunStatusInfo", 2000)
    async broadcastRunStatusInfo() {
        try {
            if (!this.server || this.server.of("").sockets.size == 0) return;
            if (this.nextBroadcastType == "cpu_usage") {
                const data = await this.deviceService.cpuUsage();
                const sdata = JSON.stringify(data);
                if (this.historyData.cpu_usage != sdata) {
                    this.historyData.cpu_usage = sdata;
                    this.server.emit(WsEvent.BROADCAST_RUN_STATUS_INFO, {
                        type: this.nextBroadcastType,
                        data,
                    });
                }
                this.nextBroadcastType = "memory";
            } else {
                const data = await this.deviceService.memory();
                const sdata = JSON.stringify(data);
                if (this.historyData.memory != sdata) {
                    this.historyData.memory = sdata;
                    this.server.emit(WsEvent.BROADCAST_RUN_STATUS_INFO, {
                        type: this.nextBroadcastType,
                        data,
                    });
                }
                this.nextBroadcastType = "cpu_usage";
            }
        } catch (error) {
            this.logger.error(error);
            this.schedulerRegistry.deleteInterval("broadcastRunStatusInfo");
        }
    }

    updateUserOnlineStatus() {
        if (!this.server) return;
        const sendToUsers: MySocket[] = [];
        const onlines: Record<number, OnlineUserItem> = {};

        this.server.of("").sockets.forEach((client: MySocket) => {
            if (client.disconnected) return;
            if (RolesGuard.verifyUser(client.user, [AdminPerm.QUERY])) sendToUsers.push(client);
            onlines[client.user.id] = {
                id: client.user.id,
                kick: client.user.id != ROOT_USER_ID,
            };
        });

        for (const client of sendToUsers) {
            const kick = onlines[client.user.id].kick;
            onlines[client.user.id].kick = false;
            client.emit(WsEvent.BROADCAST_ONLINE_USER, onlines);
            onlines[client.user.id].kick = kick;
        }
    }
}
